Skip to content

[WIP][Rough Locomotion] Part 3: G1 on Newton (max_iterations 3000→5000, no physics tuning)#5312

Draft
hujc7 wants to merge 3 commits intoisaac-sim:developfrom
hujc7:jichuanh/g1-rough-terrain-wip
Draft

[WIP][Rough Locomotion] Part 3: G1 on Newton (max_iterations 3000→5000, no physics tuning)#5312
hujc7 wants to merge 3 commits intoisaac-sim:developfrom
hujc7:jichuanh/g1-rough-terrain-wip

Conversation

@hujc7
Copy link
Copy Markdown

@hujc7 hujc7 commented Apr 19, 2026

⚠️ WIP / draft

Tracking record for G1 rough-terrain on Newton. Single-line preset bump on max_iterations. Keep open until reviewed.

1. Summary

Enable G1 rough-terrain training on Newton. The only engine-specific change is a ~1.7× bump on max_iterations (Newton = 5000, PhysX = 3000). No physics, solver, reward, or action-space tuning — the G1 rough env config is identical on both backends.

2. Dependencies

  1. PR Add checked_apply helper for forwarding configclass fields onto upstream dataclasses #5365checked_apply helper.
  2. PR [Newton] Add Rough terrain locomotion Part 1: Foundation + quadrupeds on Newton #5248 — quadruped Newton support, shared RoughPhysicsCfg, NewtonShapeCfg(margin=0.01).
  3. PR [Rough Locomotion] Part 2: H1/Cassie bipeds on Newton #5298 — biped reset overrides (G1 inherits the position_range = (1.0, 1.0) from there).

3. Core finding — PhysX saturates at iter 3000; Newton matches by iter 5000

Ran both backends for 7500 iter on identical configs. Reward alone is misleading — PhysX reward oscillates +16 to +19 across its entire run past iter 3000 without improving. Episode length confirms the plateau:

iter PhysX reward PhysX ep_len Newton reward Newton ep_len
3000 +18.14 983 +6.21 979
4000 +19.38 986 +10.65 983
5000 +18.04 978 +16.01 984
5500 +18.19 983 +16.60 985
6000 +17.07 981 +18.86 996
6500 +16.71 989 +19.80 996
7000 +16.27 968 +18.10 976
7500 +15.81 +17.56 969
  • PhysX plateau: both metrics stable at iter 3000 (+18.14 / 983). No meaningful gain past iter 3000.
  • Newton at iter 5000: (+16.01 / 984) — matches PhysX quality on both reward and ep_len.
  • Newton at iter 6000+: equals or exceeds PhysX on both metrics.

Episode length > 960 everywhere means the robot is stable (not falling) even when reward is low — reward alone is not a sufficient convergence signal.

4. Ablation record

Tested at L40, 4096 envs, seed=42, Newton @ 381781c2 (1.2.0.dev0):

Variant iter Reward Verdict
A0 — Vanilla Newton 3000 +6.21 Newton slower but learning
A1 — Newton armature 0.01 3000 +5.14 No help
A2 — Newton armature 0.03 3000 +6.43 No help
D0 — Vanilla Newton (extended) 5000 +16.01 Matches PhysX plateau quality
E0 — Vanilla PhysX 3000 +18.14 PhysX plateau

Key observations:

  • Armature tuning (0.01, 0.03) does not change Newton's convergence rate on G1.
  • Damping preset (5 → 20) and finger-removal also tested in earlier rounds; no durable benefit once Newton is given enough iterations.
  • Newton catches PhysX by iter 5000 on vanilla config, so the framework-level max_iterations bump is sufficient on its own.

5. Change

source/isaaclab_tasks/isaaclab_tasks/manager_based/locomotion/velocity/config/g1/agents/rsl_rl_ppo_cfg.py:

from isaaclab_tasks.utils import preset

class G1RoughPPORunnerCfg(RslRlOnPolicyRunnerCfg):
    # Newton needs ~1.7x the PPO iterations to match PhysX on G1. PhysX saturates near iter 3000
    # (reward ≈ +18, ep_len ≈ 980) and does not meaningfully improve on either metric past that.
    # Newton reaches the same (reward, ep_len) quality at iter 5000 (+16 / 984). The gap is
    # sample-efficiency, not a ceiling — no physics or reward tuning closes it.
    max_iterations = preset(default=3000, newton=5000)

G1 rough_env_cfg.py is unchanged vs the parent bipeds branch — no finger removal, no armature preset, no damping preset.

Precedent for per-robot max_iterations tuning: Allegro Hand (5000), Spot (20000).

6. Versions

  • isaaclab_tasks 1.5.26 → 1.5.27

Type of change

  • New feature (non-breaking).

@github-actions github-actions Bot added documentation Improvements or additions to documentation isaac-mimic Related to Isaac Mimic team labels Apr 19, 2026
Copy link
Copy Markdown

@isaaclab-review-bot isaaclab-review-bot Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR #5312 Code Review: G1 Rough-Terrain Tuning (WIP) + FrameView + Newton Improvements

This PR contains three interconnected workstreams:

  1. G1 rough-terrain locomotion tuning (WIP) with Newton-specific armature/damping presets
  2. FrameView architecture refactoring to abstract backend-specific frame views
  3. Newton backend improvements including shape margin fixes and MDP warp compatibility

Overall Assessment: REQUEST_CHANGES

While this PR contains valuable architectural improvements, there are several issues that need addressing before merge.


🔴 Critical Issues

1. preset() Function Signature Ambiguity

File: source/isaaclab_tasks/isaaclab_tasks/utils/hydra.py

The preset() function uses **kwargs with a magic default key, but this creates ambiguity when users want a preset named "default":

def preset(default=_MISSING, **kwargs):
    if default is _MISSING and "default" not in kwargs:
        raise ValueError("preset() requires 'default=' or a kwarg named 'default'")

Issue: The function allows both preset(default=X) and preset(newton=Y, default=X) but the semantics differ - in the first case default is positional, in the second it's a kwarg. This is confusing.

Recommendation: Use explicit dict construction: preset({"default": X, "newton": Y}) or require all keys be kwargs.

2. ScalarPreset Serialization Asymmetry

File: source/isaaclab_tasks/isaaclab_tasks/utils/hydra.py:46-73

The ScalarPreset class implements to_dict() but from_dict() would reconstruct a plain scalar, not a ScalarPreset. This breaks round-trip serialization:

sp = preset(default=0.01, newton=0.03)
d = sp.to_dict()  # Returns resolved scalar
# Cannot reconstruct ScalarPreset from d

Recommendation: Either document this limitation clearly or implement proper serialization.

3. Missing Type Annotations in New Termination Functions

File: source/isaaclab/isaaclab/envs/mdp/terminations.py:161-185

New functions body_lin_vel_out_of_limit and body_ang_vel_out_of_limit are missing return type annotations and have inconsistent docstring format:

def body_lin_vel_out_of_limit(
    env: ManagerBasedRLEnv,
    max_velocity: float,
    asset_cfg: SceneEntityCfg = SceneEntityCfg("robot"),
) -> torch.Tensor:  # ✓ Has return type

Good - these are correct. But the docstrings lack Args/Returns sections that other functions in this file have.


🟡 Medium Issues

4. Hardcoded CHILD_OFFSET and ATOL Constants

File: source/isaaclab/isaaclab/sim/views/usd_frame_view.py:29-30

CHILD_OFFSET = (0.1, 0.0, 0.05)
ATOL = 1e-5

These magic constants lack documentation explaining their purpose:

  • Why 0.1, 0.0, 0.05 specifically for child offset?
  • Is ATOL=1e-5 appropriate for all use cases?

Recommendation: Add docstrings explaining these values' origins and when they might need adjustment.

5. RayCaster Major Refactoring Without Migration Path

File: source/isaaclab/isaaclab/sensors/ray_caster/ray_caster.py

The complete removal of _obtain_trackable_prim_view() (75+ lines) and switch to FrameView is a breaking change. The old code had specific handling for:

  • ArticulationView detection
  • RigidBodyView detection
  • XformPrimView fallback with warnings

Issue: The new FrameView abstraction assumes the backend handles this, but there's no deprecation warning or migration guide.

Recommendation: Add a CHANGELOG entry and migration notes for users relying on the old behavior.

6. feet_slide Body ID Slicing Hack

File: source/isaaclab_tasks/isaaclab_tasks/manager_based/locomotion/velocity/mdp/rewards.py:87-88

# Use sensor body count to slice asset velocities — ensures matching dimensions
# even when Newton reports duplicate body entries for closed-loop constraints.
body_vel = wp.to_torch(asset.data.body_lin_vel_w)[:, asset_cfg.body_ids[:contacts.shape[1]], :2]

Issue: This is a workaround for a Newton backend inconsistency, not a proper fix. The comment acknowledges Newton "reports duplicate body entries" - this should be fixed in Newton, not papered over in reward functions.

Recommendation: File a follow-up issue to fix Newton's body reporting. This workaround should be temporary.

7. G1 Action Space Comment Mismatch

File: source/isaaclab_tasks/isaaclab_tasks/manager_based/locomotion/velocity/config/g1/rough_env_cfg.py:35-36

# We need to include the joints above as well, to get the 37 DOF action space.
# This is less problematic since we can let the finger joints free-floating

The PR removes 14 finger joints from the action space (37 → 23 DOF), but the comment still references "37 DOF action space". This is stale documentation.


🟢 Minor Issues / Suggestions

8. Unused Import in interactive_scene.py

File: source/isaaclab/isaaclab/scene/interactive_scene.py

The PR removes several imports but the TYPE_CHECKING block imports DeformableObject and SurfaceGripper which may not be used if those backends aren't active.

9. Test Coverage for ScalarPreset

File: source/isaaclab_tasks/test/test_hydra.py

The test file is comprehensive (1200+ lines) but I don't see explicit tests for:

  • ScalarPreset with all-same-value presets (edge case)
  • preset() with invalid/empty kwargs
  • Round-trip serialization (which would catch issue #2)

10. torch.normtorch.linalg.norm Migration

Throughout rewards.py and terminations.py, the PR migrates from deprecated torch.norm to torch.linalg.norm. This is good practice, but should be noted in the PR description for searchability.


✅ Positive Observations

  1. FrameView Architecture: The BaseFrameViewFrameView → backend-specific implementations pattern is clean and follows good OOP principles.

  2. preset() Hydra Integration: The concept of backend-conditional values (preset(default=X, newton=Y)) is elegant for multi-backend configs.

  3. Newton Shape Margin Fix: The CHANGELOG entry for contact_marginmargin typo fix is well-documented.

  4. Test Infrastructure: The expanded test_hydra.py with 1200+ lines of tests shows good coverage of the new preset system.

  5. Warp Compatibility: The systematic wp.to_torch() wrapping in MDP functions enables Newton backend support.


Recommended Actions

  1. Clarify preset() function signature - consider explicit dict API
  2. Document magic constants in usd_frame_view.py
  3. Fix stale comment about 37 DOF in G1 config
  4. Add migration notes for RayCaster changes
  5. File follow-up issue for Newton duplicate body entries
  6. Add missing test cases for ScalarPreset edge cases

Reviewed at commit: a67b001

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Magic Constants: CHILD_OFFSET and ATOL lack documentation.

  • Why (0.1, 0.0, 0.05) for CHILD_OFFSET?
  • What is the origin of ATOL=1e-5?

Please add docstrings explaining these constants' purpose and when users might need to adjust them.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Workaround for Newton Bug: The slicing asset_cfg.body_ids[:contacts.shape[1]] papers over a Newton backend issue.

The comment says Newton "reports duplicate body entries for closed-loop constraints" - this should be fixed in Newton itself, not worked around in reward functions.

Suggestion: File a follow-up issue to fix Newton's body reporting and mark this as a temporary workaround with a TODO.

Copy link
Copy Markdown

@isaaclab-review-bot isaaclab-review-bot Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WIP PR Review: G1 Rough-Terrain Tuning

Reviewed the WIP commit a67b0017 which adds G1-specific rough terrain tuning on top of the parent PR #5298.

Summary

This is a well-documented WIP PR that addresses a real training issue (14 finger joints inflating action_rate_l2 penalty 3× vs H1) and applies the established Newton armature/damping preset pattern from Go2. The measured results (+20.54 PhysX, +9.61 Newton) demonstrate meaningful improvement.

Overall

For a WIP PR focused on recording tuning progress, this is clean and well-structured. The code follows established patterns (preset() for Newton-specific values, actuators["legs"] matching the G1_CFG definition). The detailed PR description with measured results is appreciated.

When promoting from WIP:

  • Consider whether the damping bump (5.0→20.0) is worth the base_contact regression noted in the PR description (7%→18.7%)
  • The armature-only variant (+8.10 reward) may be a cleaner landing point than armature+damping (+9.61 with contact regression)
  • As noted in the PR, this could potentially be split: fingers-out-of-action fix (clean PhysX improvement) could land independently of the Newton tuning work

No blocking issues found. The one inline comment is a minor documentation fix.

# terminations
self.terminations.base_contact.params["sensor_cfg"].body_names = "torso_link"

# G1 H1: remove finger joints from the action space. 14 finger joints contribute
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor typo: "G1 H1" should be "G1" - H1 doesn't have finger joints (H1 only has legs, feet, and arms actuator groups).

Suggested change
# G1 H1: remove finger joints from the action space. 14 finger joints contribute
# G1: remove finger joints from the action space. 14 finger joints contribute

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Stale Documentation: Comments in this file reference "37 DOF action space" but this PR removes 14 finger joints, reducing the action space to 23 DOF.

Please update the comments to reflect the actual action space dimensions after finger joint removal.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Breaking Change: The complete removal of _obtain_trackable_prim_view() (75+ lines) is a significant refactoring.

The old code had specific handling for:

  • ArticulationView detection via UsdPhysics.ArticulationRootAPI
  • RigidBodyView detection via UsdPhysics.RigidBodyAPI
  • XformPrimView fallback with helpful warning messages

Please add a CHANGELOG entry and migration notes for users who may have been relying on the old behavior or its warning messages.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good Addition: The new body_lin_vel_out_of_limit and body_ang_vel_out_of_limit functions are useful safety checks that can prevent NaN propagation from solver singularities.

Minor suggestion: Consider adding Args/Returns sections to the docstrings for consistency with other functions in this file.

@hujc7 hujc7 force-pushed the jichuanh/g1-rough-terrain-wip branch from a67b001 to a4d0ebc Compare April 20, 2026 10:25
@isaaclab-review-bot isaaclab-review-bot Bot dismissed their stale review April 21, 2026 16:17

Dismissing: bot incorrectly used CHANGES_REQUESTED. Bot policy is COMMENT-only — never APPROVE or REQUEST_CHANGES.

@hujc7 hujc7 changed the title [WIP] G1 rough-terrain: fingers-out-of-action + Newton armature/damping tuning [WIP][Rough Locomotion] Part 3: G1 Newton fixes Apr 22, 2026
@hujc7 hujc7 force-pushed the jichuanh/g1-rough-terrain-wip branch from a4d0ebc to ccbd6f0 Compare April 22, 2026 19:19
@hujc7 hujc7 changed the title [WIP][Rough Locomotion] Part 3: G1 Newton fixes [WIP][Rough Locomotion] Part 3: G1 on Newton (2x iter budget, no physics tuning) Apr 22, 2026
@hujc7 hujc7 force-pushed the jichuanh/g1-rough-terrain-wip branch from ccbd6f0 to 99f50d7 Compare April 22, 2026 19:27
@hujc7 hujc7 changed the title [WIP][Rough Locomotion] Part 3: G1 on Newton (2x iter budget, no physics tuning) [WIP][Rough Locomotion] Part 3: G1 on Newton (max_iterations 3000→5000, no physics tuning) Apr 22, 2026
Copy link
Copy Markdown

@isaaclab-review-bot isaaclab-review-bot Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Isaac Lab Review Bot

Summary

This PR (Part 3 of rough locomotion) adds Newton backend support for the G1 biped on rough terrain. The implementation is minimal and well-documented: a single preset(default=3000, newton=5000) on max_iterations in G1RoughPPORunnerCfg is the only G1-specific change. The PR description provides thorough ablation data showing Newton reaches PhysX-equivalent quality (reward ≈ +16, ep_len ≈ 984) at iter 5000 vs PhysX's plateau at iter 3000.

This is a clean, well-scoped change. The decision to bump iteration budget rather than tune physics/reward terms keeps the env config engine-agnostic, following precedent from Allegro Hand (5000 iter) and Spot (20000 iter).

Architecture Impact

No cross-module impact from the G1-specific changes. The max_iterations preset is localized to the PPO runner config. The rest of the PR stacks parent changes from #5298 (biped Newton support) and #5248 (quadruped Newton support), which have broader impact but were covered in prior reviews.

Implementation Verdict

Ship it — The G1-specific change (commit 99f50d7d) is correct and follows established patterns. The comment explains the rationale thoroughly.

Test Coverage

Acceptable for this change type. This is a hyperparameter tuning PR (iteration count), not a code behavior change. The existing rough-terrain training infrastructure provides implicit coverage. The PR description includes ablation data demonstrating the change achieves parity:

iter PhysX reward PhysX ep_len Newton reward Newton ep_len
3000 +18.14 983 +6.21 979
5000 +18.04 978 +16.01 984

The data validates the 5000 iteration preset is sufficient for Newton to match PhysX plateau quality.

CI Status

Only labeler check is present (passed ✅). No pre-commit/lint/test failures detected.

Branch Status

⚠️ This branch has diverged from develop (30 commits behind, 29 ahead). Consider rebasing before merge to pick up recent changes and ensure CI runs against current develop.

Findings

No new issues found in the G1-specific changes (commit 99f50d7d). The change is minimal, well-documented, and follows established patterns.

Prior review comments still applicable: The stacked commits from parent PRs have existing review comments (FrameView constants documentation, Newton body reporting workaround, etc.) that should be addressed in those parent PRs.


Reviewed at commit: 99f50d7

@hujc7
Copy link
Copy Markdown
Author

hujc7 commented Apr 24, 2026

@greptileai Review — please re-review. Force-pushed onto updated #5298 base (rebase only; no content change in this PR's own commit). Stack: #5365#5248#5298#5312.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 24, 2026

Greptile Summary

This PR enables G1 rough-terrain training on Newton by bumping max_iterations to a backend-aware preset(default=3000, newton=5000), backed by empirical data showing Newton reaches PhysX-quality convergence at iter 5000. It also bundles a set of biped-wide stabilization fixes: re-enabling add_base_mass randomization for H1 and Cassie (with an asymmetric (1.0, 1.25) scale for Cassie), a Newton-only armature preset for Cassie, and pinning reset_robot_joints.position_range = (1.0, 1.0) across G1, H1, Cassie, and Digit.

Confidence Score: 5/5

Safe to merge; all findings are P2 suggestions with no correctness or safety impact.

No P0 or P1 issues found. The single P2 note (flat-config max_iterations plain-int override) is a pre-existing pattern and intentionally out of scope for this PR. All behavioral changes are well-justified by empirical data and consistent with the biped-reset convention established in dependent PRs.

No files require special attention.

Important Files Changed

Filename Overview
source/isaaclab_tasks/isaaclab_tasks/manager_based/locomotion/velocity/config/g1/agents/rsl_rl_ppo_cfg.py Introduces preset(default=3000, newton=5000) for rough-terrain max_iterations; flat-config subclass still overrides with plain int 1500.
source/isaaclab_tasks/isaaclab_tasks/manager_based/locomotion/velocity/config/g1/rough_env_cfg.py Adds reset_robot_joints.position_range = (1.0, 1.0) to pin G1 to exact default joint positions on reset; no other changes.
source/isaaclab_tasks/isaaclab_tasks/manager_based/locomotion/velocity/config/h1/rough_env_cfg.py Re-enables add_base_mass for H1 with body_names override; adds reset_robot_joints.position_range = (1.0, 1.0).
source/isaaclab_tasks/isaaclab_tasks/manager_based/locomotion/velocity/config/cassie/rough_env_cfg.py Re-enables asymmetric mass randomization (1.0, 1.25) for Cassie, adds Newton-only armature preset 0.02, and pins joint reset range to (1.0, 1.0).
source/isaaclab_tasks/isaaclab_tasks/manager_based/locomotion/velocity/config/digit/rough_env_cfg.py Adds reset_robot_joints.position_range = (1.0, 1.0) for Digit, consistent with the biped-reset pattern applied to all four bipeds in this PR.
source/isaaclab_tasks/config/extension.toml Version bump 1.5.28 to 1.5.30 to cover two new CHANGELOG entries (1.5.29 H1/Cassie, 1.5.30 G1 Newton).
source/isaaclab_tasks/docs/CHANGELOG.rst Adds well-documented 1.5.29 and 1.5.30 changelog entries explaining the H1/Cassie and G1 changes respectively.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[G1RoughPPORunnerCfg] -->|max_iterations| B{preset}
    B -->|PhysX| C[3000 iterations]
    B -->|Newton| D[5000 iterations]
    E[G1FlatPPORunnerCfg] -->|post_init override| F[1500 iterations both backends]
    E -.->|inherits| A

    G[CassieRoughEnvCfg] -->|mass_distribution_params| H[1.0 to 1.25 scale - heavier only]
    G -->|armature preset| I{preset}
    I -->|PhysX| J[0.0]
    I -->|Newton| K[0.02]

    L[H1RoughEnvCfg] -->|add_base_mass| M[shared log-uniform scale default]

    N[G1 + H1 + Cassie + Digit] -->|reset_robot_joints position_range| O[1.0 to 1.0 - exact defaults]
Loading

Reviews (2): Last reviewed commit: "Bump G1 max_iterations to 5000 on Newton..." | Re-trigger Greptile

Comment on lines 326 to 330
body_lin_vel = DoneTerm(
func=mdp.body_lin_vel_out_of_limit,
params={"max_velocity": 20.0, "asset_cfg": SceneEntityCfg("robot", body_names=".*")},
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 New body_lin_vel termination applies to every rough-terrain env

body_lin_vel_out_of_limit at 20 m/s is now a universal termination condition across all rough-terrain robots (Anymal, Go1/2, A1, H1, Cassie, Digit, G1). While 20 m/s is a generous safety cap and the intent (catching simulation explosions) is good, this is an additive behavioral change for all existing environments that wasn't present before. If any robot canonically reaches near that speed during certain reset conditions or in edge-case terrain interactions, the episode will silently terminate differently than before — worth verifying the threshold is safe for the lightest/fastest robots (Go1, A1) under aggressive push events.

@hujc7 hujc7 force-pushed the jichuanh/g1-rough-terrain-wip branch 3 times, most recently from 1660543 to b3bfb39 Compare April 24, 2026 06:23
@hujc7 hujc7 force-pushed the jichuanh/g1-rough-terrain-wip branch 2 times, most recently from 9e8f462 to 6aba4c0 Compare April 24, 2026 09:15
kellyguo11 added a commit that referenced this pull request Apr 26, 2026
…eam dataclasses (#5365)

# Description

Adds `isaaclab.utils.checked_apply` for forwarding the declared fields
of one dataclass onto another, raising `AttributeError` if the target is
missing a declared field.

The use case is Isaac Lab configclasses that mirror an upstream
library's dataclass (for example, Newton's `ShapeConfig`). Bare
`setattr` loops are fragile: if upstream renames or removes a field,
every write becomes a silent no-op (the failure mode PR #5289 fixed for
`ShapeConfig.contact_margin` → `margin`). With `checked_apply`, the
failure surfaces at startup with a clear message instead of degrading
runtime behavior.

## API

```python
from isaaclab.utils import checked_apply

@configclass
class NewtonShapeCfg:
    margin: float = 0.0
    gap: float = 0.01

# at apply site (one line, no per-field setattr noise)
checked_apply(cfg.default_shape_cfg, builder.default_shape_cfg)
```

Internally:
1. Iterates `dataclasses.fields(src)` — single source of truth for
declared fields.
2. Raises `AttributeError` if `target` lacks a declared field.
3. Rejects non-dataclass `src` with `TypeError`.

## What's included

1. `source/isaaclab/isaaclab/utils/configclass.py` — `checked_apply`
function (lives next to `@configclass` since it operates on
dataclasses).
2. `source/isaaclab/isaaclab/utils/__init__.pyi` — export.
3. `source/isaaclab/test/utils/test_configclass.py` — three tests
(forwards all fields, raises on missing target field, rejects
non-dataclass src).
4. `source/isaaclab/docs/CHANGELOG.rst` — `4.6.13` entry.
5. `source/isaaclab/config/extension.toml` — version bump.

## Dependents

This PR is a dependency for the rough-terrain Newton stack:

1. PR #5248 — quadrupeds rough terrain, uses `checked_apply` to forward
`NewtonShapeCfg` onto Newton's upstream `ShapeConfig`. Without it,
`default_shape_cfg.margin` is left at Newton's upstream default of
`0.0`, breaking all non-Anymal-D robots on triangle-mesh terrain.
2. PR #5298 — bipeds (chains on #5248).
3. PR #5312 — G1 (chains on #5298).

## Type of change

- New feature (non-breaking).

## Checklist

- [x] Tests added (3 new in `test_configclass.py`)
- [x] Pre-commit checks pass
- [x] CHANGELOG + extension.toml bumped
- [x] No new dependencies

---------

Signed-off-by: Kelly Guo <kellyg@nvidia.com>
Co-authored-by: Kelly Guo <kellyg@nvidia.com>
hujc7 added 3 commits April 27, 2026 06:43
Restore per-biped overrides dropped by parent PR's consolidation:
- All bipeds (H1, Cassie, G1, Digit): restore
  reset_robot_joints.params["position_range"] = (1.0, 1.0). Bipeds
  have precise init poses that should not be randomly scaled on reset.
- Cassie: add leg armature=0.02 for stability on rough terrain.

Out of scope (pre-existing issues that fail on PhysX too):
- G1: finger joints dilute learning; addressed in follow-up PR.
- Digit: closed-loop kinematics fail in 7 steps on both backends.
Restore base-mass randomization on H1 and Cassie that was disabled with
add_base_mass = None in their rough-terrain configs (pre-existing biped
convention from 2024-06 PR isaac-sim#444, later reinforced by PR isaac-sim#4165's Newton NaN
TODO). The parent PR isaac-sim#5248 switches the shared default to log-uniform scale
(1/1.25, 1.25), which is safer for bipeds than the old additive (-5, 5) kg
(effectively ±25% on H1's torso vs ±100% on Cassie's pelvis).

- H1 inherits the shared default (symmetric ±25% scale, body_names="torso_link").
- Cassie overrides to (1.0, 1.25) asymmetric heavier-bias: lighter-than-
  nominal pelvis destabilizes Cassie's closed-loop Achilles rod coupling
  and hip PD response, while heavier-than-nominal dampens dynamics.

| Variant                        | reward | ep len | vs disabled |
|--------------------------------|-------:|-------:|------------:|
| None (disabled, prior default) |  23.93 |    910 |     1.00x   |
| (1/1.25, 1.25) sym25           |  14.15 |    850 |     0.59x x |
| (1/1.10, 1.10) tight10         |  14.53 |    831 |     0.61x x |
| **(1.0, 1.25) heavier25**      | **21.50** | **932** | **0.90x** |

Tightening the range symmetrically did not help (tight10 ~ sym25) — the
lighter side is what destabilizes, not the magnitude. Restricting to
[1.0, 1.25] (never lighter, up to +25% heavier) preserves most of the
randomization benefit while avoiding the failure mode. Episode length
also improves (932 vs 910), indicating the randomized policy is actively
more stable during episodes — the lower aggregate reward comes from extra
dof-torque regularizer paid to handle heavier instances, not degraded
task completion.

H1's larger base mass (≈15 kg torso) means ±25% on the default scale
(11-19 kg range) is well within the controller's robustness margin. H1
reward at iter 1499: 24.02 with mass rand on vs 23.58 with it disabled
(1.02x, essentially equal). Re-enabling provides sim-to-real robustness
at negligible training cost.
PhysX G1 saturates near iter 3000: reward ≈ +18, ep_len ≈ 980.
Past iter 3000 PhysX does not meaningfully improve on either metric —
reward oscillates +16-19 through iter 7500, ep_len stays flat.

Newton vanilla reaches matching (reward, ep_len) = (+16, 984) at
iter 5000 and equals/exceeds PhysX by iter 6000 (+18.9 / 996). The
gap is sample-efficiency, not a ceiling.

Ablation (armature 0.01/0.03, damping 5→20, finger-removal from action
space, Newton upstream a27277) did not change Newton's curve shape.
Use the framework preset on max_iterations rather than tuning physics
or reward terms, keeping the env config engine-agnostic. Precedent:
Allegro Hand (5000), Spot (20000).
@hujc7 hujc7 force-pushed the jichuanh/g1-rough-terrain-wip branch from 6aba4c0 to 2465348 Compare April 27, 2026 06:45
@hujc7
Copy link
Copy Markdown
Author

hujc7 commented Apr 27, 2026

@greptileai Review — please re-review on the freshly rebased HEAD.

Stack collapsed: #5365 + #5248 + #5298's parents merged to develop on 2026-04-26. This PR has been rebased onto current develop + #5298 and now contains only the single G1 commit:

Bump G1 max_iterations to 5000 on Newton for rough-terrain paritymax_iterations = preset(default=3000, newton=5000) on G1RoughPPORunnerCfg. No physics, solver, reward, or action-space tuning. CHANGELOG bumped to 1.5.30.

Empirical evidence: PhysX saturates near iter 3000 (reward ≈ +18, ep_len ≈ 980); Newton reaches matching (reward, ep_len) at iter 5000 (+16 / 984). Both backends plateau at +16-19 thereafter. Ablation (armature 0.01/0.03, damping, finger-removal) showed no acceleration of Newton convergence.

Earlier dismissed isaaclab-review-bot findings about finger removal / 37 DOF / FrameView are stale — finger removal was dropped from this PR; FrameView landed via #5179.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation isaac-lab Related to Isaac Lab team isaac-mimic Related to Isaac Mimic team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant